home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 11 / Mac Magazin and MacEasy Magazine CD - Issue 11.iso / Sharewarebibliothek / Entwickler / WASTE 1.1b1 Distribution / WASTE Source / WEInlineInput.p < prev    next >
Text File  |  1995-06-01  |  17KB  |  618 lines

  1. unit WEInlineInput;
  2.  
  3. { WASTE PROJECT: }
  4. { Inline Input Support }
  5.  
  6. { Copyright © 1993-1995 Marco Piovanelli }
  7. { All Rights Reserved }
  8.  
  9. interface
  10.     uses
  11.         WEHighLevelEditing;
  12.  
  13.     function WEInstallTSMHandlers: OSErr;
  14.     function WERemoveTSMHandlers: OSErr;
  15.  
  16. implementation
  17.     uses
  18.         AERegistry;
  19.  
  20. {$IFC WASTE_SEGMENT}
  21. {$S WASTE_TSM_SUPPORT}
  22. {$ENDC}
  23.  
  24.     var
  25.  
  26. { static variables }
  27.  
  28.         _weUpdateActiveInputAreaHandler: AEEventHandlerUPP;
  29.         _wePositionToOffsetHandler: AEEventHandlerUPP;
  30.         _weOffsetToPositionHandler: AEEventHandlerUPP;
  31.  
  32.     function _WEHiliteRangeArray (hTray: TextRangeArrayHandle;
  33.                                     hWE: WEHandle): OSErr;
  34.         label
  35.             1;
  36.         var
  37.             pWE: WEPtr;
  38.             pRange: TextRangePtr;
  39.             rangeStart, rangeEnd: LongInt;
  40.             hiliteStyle: Integer;
  41.             ts: WETextStyle;
  42.             rangeIndex: Integer;
  43.             saveTrayLock: Boolean;
  44.             err: OSErr;
  45.     begin
  46.         pWE := hWE^;
  47.  
  48. { lock down the range array }
  49.         saveTrayLock := _WESetHandleLock(hTray, true);
  50.         rangeIndex := hTray^^.fNumOfRanges - 1;
  51.         pRange := @hTray^^.fRange;
  52.  
  53. { walk the hilite range array }
  54.         while (rangeIndex >= 0) do
  55.             begin
  56.  
  57. { the offsets in the range array are relative to the beginning }
  58. { of the active input area: convert them to absolute offsets }
  59.                 rangeStart := pWE^.tsmAreaStart + pRange^.fStart;
  60.                 rangeEnd := pWE^.tsmAreaStart + pRange^.fEnd;
  61.                 hiliteStyle := pRange^.fHiliteStyle;
  62.  
  63. { take the absolute value of hiliteStyle }
  64.                 hiliteStyle := ABS(hiliteStyle);
  65.  
  66. { if hiliteStyle is kCaretPosition, set the selection range }
  67.                 if (hiliteStyle = kCaretPosition) then
  68.                     begin
  69.                         pWE^.selStart := rangeStart;
  70.                         pWE^.selEnd := rangeEnd;
  71.                     end
  72.                 else
  73.                     begin
  74.                         hiliteStyle := hiliteStyle - kRawText;
  75.  
  76. { otherwise set the WETextStyle flags of the specified range appropriately }
  77.                         if ((hiliteStyle >= 0) and (hiliteStyle <= 3)) then
  78.                             begin
  79.                                 ts.tsFlags := $10 + BSL(hiliteStyle, tsTSMSelected);
  80.                                 err := _WESetStyleRange(rangeStart, rangeEnd, weDoFlags, ts, hWE);
  81.                                 if (err <> noErr) then
  82.                                     goto 1;
  83.                             end;
  84.                     end;
  85.  
  86. { go to next text range element }
  87.                 rangeIndex := rangeIndex - 1;
  88.                 pRange := TextRangePtr(LongInt(pRange) + SizeOf(TextRange));
  89.             end;  { while }
  90.  
  91. { clear result code }
  92.         err := noErr;
  93.  
  94. 1:
  95. { unlock the range array }
  96.         if (_WESetHandleLock(hTray, saveTrayLock)) then
  97.             ;
  98.  
  99. { return result code }
  100.         _WEHiliteRangeArray := err;
  101.  
  102.     end;  { _WEHiliteRangeArray }
  103.  
  104.     function _WEHandleUpdateActiveInputArea (var ae, reply: AppleEvent;
  105.                                     handlerRefCon: LongInt): OSErr;
  106.         label
  107.             1;
  108.         var
  109.             hWE: WEHandle;
  110.             pWE: WEPtr;
  111.             text: AEDesc;
  112.             hiliteTray: AEDesc;
  113.             pinRange: TextRange;
  114.             totalLength: LongInt;
  115.             fixLength: LongInt;
  116.             tsmOffset: LongInt;
  117.             returnedType: DescType;
  118.             actualSize: LongInt;
  119.             savePort: GrafPtr;
  120.             hAction: WEActionHandle;
  121.             saveAutoScroll: Boolean;
  122.             saveTextLock: Boolean;
  123.             saveWELock: Boolean;
  124.             err: OSErr;
  125.     begin
  126.         hWE := nil;
  127.  
  128. { initialize descriptors to null values }
  129.         text.descriptorType := typeNull;
  130.         text.dataHandle := nil;
  131.         hiliteTray.descriptorType := typeNull;
  132.         hiliteTray.dataHandle := nil;
  133.  
  134. { extract WE handle }
  135.         err := AEGetParamPtr(ae, keyAETSMDocumentRefCon, typeLongInteger, returnedType, @hWE, SizeOf(hWE), actualSize);
  136.         if (err <> noErr) then
  137.             goto 1;
  138.  
  139. { lock the WE handle }
  140.         saveWELock := _WESetHandleLock(hWE, true);
  141.         pWE := hWE^;
  142.  
  143. { return an error code if the read-only flag is set }
  144.         err := weReadOnlyErr;
  145.         if (BTST(pWE^.flags, weFReadOnly)) then
  146.             goto 1;
  147.  
  148. { call the pre-update callback, if present }
  149.         if (pWE^.tsmPreUpdate <> nil) then
  150.             CallWETSMPreUpdateProc(hWE, pWE^.tsmPreUpdate);
  151.  
  152. { hide the caret if it's showing }
  153.         if BTST(pWE^.flags, weFCaretVisible) then
  154.             _WEBlinkCaret(hWE);
  155.  
  156. { extract the text descriptor }
  157.         err := AEGetParamDesc(ae, keyAETheData, typeChar, text);
  158.         if (err <> noErr) then
  159.             goto 1;
  160.  
  161. { get total length of text in the active input area }
  162.         totalLength := GetHandleSize(text.dataHandle);
  163.  
  164. { extract the length of confirmed text in the active input area }
  165.         err := AEGetParamPtr(ae, keyAEFixLength, typeLongInteger, returnedType, @fixLength, SizeOf(fixLength), actualSize);
  166.         if (err <> noErr) then
  167.             goto 1;
  168.  
  169. { if fixLength = -1, all text is confirmed }
  170.         if (fixLength = -1) then
  171.             fixLength := totalLength;
  172.  
  173. { if there's currently no active input area, open one }
  174.         if (pWE^.tsmAreaStart = kInvalidOffset) then
  175.             begin
  176.                 pWE^.tsmAreaStart := pWE^.selStart;
  177.                 pWE^.tsmAreaEnd := pWE^.selEnd;
  178.  
  179. { are we tracking a typing sequence? }
  180.                 if (WEIsTyping(hWE) = false) then
  181.                     begin
  182.  
  183. { nope; so start a new one }
  184. { increment modification count }
  185.                         pWE^.modCount := pWE^.modCount + 1;
  186.  
  187. { if undo support is enabled, create a new action to keep track of the typing }
  188.                         if (BTST(pWE^.flags, weFUndoSupport)) then
  189.                             begin
  190.                                 WEClearUndo(hWE);
  191.                                 if (WENewAction(pWE^.selStart, pWE^.selEnd, 0, weAKTyping, 0, hWE, hAction) = noErr) then
  192.                                     if (WEPushAction(hAction) <> noErr) then
  193.                                         ;
  194.                             end;
  195.                     end;
  196.             end;
  197.  
  198.         tsmOffset := pWE^.tsmAreaStart;
  199.  
  200. { the new text replaces whatever is in the active input area }
  201.         err := _WEDeleteRange(tsmOffset, pWE^.tsmAreaEnd, hWE);
  202.         if (err <> noErr) then
  203.             goto 1;
  204.  
  205. { synchronize the null style, so font script matches the keyboard script }
  206.         _WESynchNullStyle(hWE);
  207.  
  208. { set the port font for good measure }
  209.         GetPort(savePort);
  210.         SetPort(pWE^.port);
  211.         TextFont(pWE^.nullStyle.runStyle.tsFont);
  212.         SetPort(savePort);
  213.  
  214. { temporarily lock the text }
  215.         saveTextLock := _WESetHandleLock(text.dataHandle, true);
  216.  
  217. { insert the text }
  218.         err := _WEInsertText(tsmOffset, text.dataHandle^, totalLength, hWE);
  219.         if (err <> noErr) then
  220.             goto 1;
  221.  
  222. { unlock the text }
  223.         if (_WESetHandleLock(text.dataHandle, saveTextLock)) then
  224.             ;
  225.  
  226. { extract pin range }
  227.         err := AEGetParamPtr(ae, keyAEPinRange, typeTextRange, returnedType, @pinRange, SizeOf(pinRange), actualSize);
  228.         if (err = noErr) then
  229.             begin
  230.  
  231. { we want absolute offsets }
  232.                 pinRange.fStart := pinRange.fStart + tsmOffset;
  233.                 pinRange.fEnd := pinRange.fEnd + tsmOffset;
  234.             end
  235.         else
  236.             begin
  237.  
  238. { a missing pin range descriptor isn't an error; everything else is }
  239.                 if (err <> errAEDescNotFound) then
  240.                     goto 1;
  241.  
  242. { default pin range is active input area }
  243.                 pinRange.fStart := tsmOffset;
  244.                 pinRange.fEnd := pWE^.tsmAreaEnd;
  245.             end;
  246.  
  247. { NOTE: if fixLength = totalLength, the inline input session is over, so, in theory, }
  248. { hiliteTray should either be missing or not specify any range to be underlined. }
  249. { Unfortunately, some input methods (like Apple's input method for Simplified Chinese) }
  250. { do specify kConvertedText (= thin black underline) for the whole text when }
  251. { the text is confirmed (is this a bug?).  To work around this, we deliberately ignore }
  252. { the hiliteTray parameter when fixLength = totalLength. }
  253.  
  254.         if (fixLength <> totalLength) then
  255.             begin
  256.  
  257. { extract the highlight range array }
  258.                 err := AEGetParamDesc(ae, keyAEHiliteRange, typeTextRangeArray, hiliteTray);
  259.                 if (err <> noErr) then
  260.                     if (err <> errAEDescNotFound) then
  261.                         goto 1;
  262.  
  263.             end;
  264.  
  265.         if (hiliteTray.dataHandle <> nil) then
  266.             begin
  267.                 err := _WEHiliteRangeArray(TextRangeArrayHandle(hiliteTray.dataHandle), hWE);
  268.                 if (err <> noErr) then
  269.                     goto 1;
  270.             end
  271.         else
  272.             begin
  273.                 pWE^.selStart := tsmOffset + fixLength;
  274.                 pWE^.selEnd := pWE^.selStart;
  275.             end;
  276.  
  277. { temporarily disable auto-scroll, as we need to scroll manually according to pinRange }
  278.         saveAutoScroll := BTST(pWE^.flags, weFAutoScroll);
  279.         BCLR(pWE^.flags, weFAutoScroll);
  280.  
  281. { redraw the active input area }
  282.         err := _WERedraw(tsmOffset, tsmOffset + totalLength, hWE);
  283.         if (err <> noErr) then
  284.             goto 1;
  285.  
  286.         if (saveAutoScroll) then
  287.             begin
  288.  
  289. { re-enable auto-scroll }
  290.                 BSET(pWE^.flags, weFAutoScroll);
  291.  
  292. { scroll the pin range into view }
  293.                 if (_WEScrollIntoView(pinRange.fStart, hWE) = false) then
  294.                     if (pinRange.fStart <> pinRange.fEnd) then
  295.                         if (_WEScrollIntoView(pinRange.fEnd, hWE)) then
  296.                             ;
  297.             end;
  298.  
  299. { update the boundaries of the active input area }
  300. { if fixLength = totalLength, the inline input session is over: close the active input area }
  301.         if (fixLength = totalLength) then
  302.             begin
  303.                 pWE^.tsmAreaStart := kInvalidOffset;
  304.                 pWE^.tsmAreaEnd := kInvalidOffset;
  305.  
  306. { adjust undo buffer (if any) for the confirmed text }
  307.                 _WEAdjustUndoRange(fixLength, hWE);
  308.             end
  309.         else
  310.             begin
  311.  
  312. { otherwise, fixLength defines the boundaries of the active input area }
  313.                 pWE^.tsmAreaStart := tsmOffset + fixLength;
  314.                 pWE^.tsmAreaEnd := tsmOffset + totalLength;
  315.             end;
  316.  
  317. { call the post-update callback, if present }
  318.         if (pWE^.tsmPostUpdate <> nil) then
  319.             CallWETSMPostUpdateProc(hWE, fixLength, pWE^.tsmAreaStart, pWE^.tsmAreaEnd, pinRange.fStart, pinRange.fEnd, pWE^.tsmPostUpdate);
  320.  
  321. { clear result code }
  322.         err := noErr;
  323.  
  324. 1:
  325. { clean up }
  326.         if (AEDisposeDesc(text) <> noErr) then
  327.             ;
  328.         if (AEDisposeDesc(hiliteTray) <> noErr) then
  329.             ;
  330.  
  331. { unlock the WE record }
  332.         if (_WESetHandleLock(hWE, saveWELock)) then
  333.             ;
  334.  
  335. { return result code }
  336.         _WEHandleUpdateActiveInputArea := err;
  337.  
  338.     end;  { _WEHandleUpdateActiveInputArea }
  339.  
  340.     function _WEHandlePositionToOffset (var ae, reply: AppleEvent;
  341.                                     handlerRefCon: LongInt): OSErr;
  342.         label
  343.             1;
  344.         var
  345.             hWE: WEHandle;
  346.             pWE: WEPtr;
  347.             position: Point;
  348.             thePoint: LongPt;
  349.             regionClass: Integer;
  350.             offset: LongInt;
  351.             returnedType: DescType;
  352.             actualSize: LongInt;
  353.             savePort: GrafPtr;
  354.             edge: SignedByte;
  355.             saveWELock: Boolean;
  356.             err: OSErr;
  357.     begin
  358.         hWE := nil;
  359.  
  360. { extract WE handle }
  361.         err := AEGetParamPtr(ae, keyAETSMDocumentRefCon, typeLongInteger, returnedType, @hWE, SizeOf(hWE), actualSize);
  362.         if (err <> noErr) then
  363.             goto 1;
  364.  
  365. { lock the WE record }
  366.         saveWELock := _WESetHandleLock(hWE, true);
  367.         pWE := hWE^;
  368.  
  369. { extract position parameter }
  370.         err := AEGetParamPtr(ae, keyAECurrentPoint, typeQDPoint, returnedType, @position, SizeOf(position), actualSize);
  371.         if (err <> noErr) then
  372.             goto 1;
  373.  
  374. { convert position to local... }
  375.         GetPort(savePort);
  376.         SetPort(pWE^.port);
  377.         GlobalToLocal(position);
  378.         SetPort(savePort);
  379.  
  380. { ...and long coordinates }
  381.         WEPointToLongPoint(position, thePoint);
  382.  
  383. { find the byte offset and the edge value corresponding to the given position }
  384.         offset := WEGetOffset(thePoint, edge, hWE);
  385.  
  386. { determine the region class }
  387.         if (WELongPointInLongRect(thePoint, pWE^.viewRect)) then
  388.             if (_WEOffsetInRange(offset, edge, pWE^.tsmAreaStart, pWE^.tsmAreaEnd)) then
  389.                 begin
  390.                     regionClass := kTSMInsideOfActiveInputArea;
  391.  
  392. { if the given position is within the active input area, we're supposed to return }
  393. { an offset relative to the beginning of this area (thanks, Martin!) }
  394.                     offset := offset - pWE^.tsmAreaStart;
  395.                 end
  396.             else
  397.                 begin
  398.  
  399. { otherwise the offset is relative to the beginning of the body }
  400.                     regionClass := kTSMInsideOfBody;
  401.                 end
  402.         else
  403.             regionClass := kTSMOutsideOfBody;
  404.  
  405. { add region class parameter to reply }
  406.         err := AEPutParamPtr(reply, keyAERegionClass, typeShortInteger, @regionClass, SizeOf(regionClass));
  407.         if (err <> noErr) then
  408.             goto 1;
  409.  
  410. { add offset parameter to reply }
  411.         err := AEPutParamPtr(reply, keyAEOffset, typeLongInteger, @offset, SizeOf(offset));
  412.         if (err <> noErr) then
  413.             goto 1;
  414.  
  415. { add edge parameter to reply }
  416.         err := AEPutParamPtr(reply, keyAELeftSide, typeBoolean, @edge, SizeOf(edge));
  417.         if (err <> noErr) then
  418.             goto 1;
  419.  
  420. { clear result code }
  421.         err := noErr;
  422.  
  423. 1:
  424. { unlock the WE record }
  425.         if (hWE <> nil) then
  426.             if (_WESetHandleLock(hWE, saveWELock)) then
  427.                 ;
  428.  
  429. { return result code }
  430.         _WEHandlePositionToOffset := err;
  431.  
  432.     end;  { _WEHandlePositionToOffset }
  433.  
  434.     function _WEHandleOffsetToPosition (var ae, reply: AppleEvent;
  435.                                     handlerRefCon: LongInt): OSErr;
  436.         label
  437.             1;
  438.         var
  439.             hWE: WEHandle;
  440.             pWE: WEPtr;
  441.             offset: LongInt;
  442.             thePoint: LongPt;
  443.             position: Point;
  444.             lineHeight: Integer;
  445.             returnedType: DescType;
  446.             actualSize: LongInt;
  447.             savePort: GrafPtr;
  448.             saveWELock: Boolean;
  449.             err: OSErr;
  450.     begin
  451.         hWE := nil;
  452.  
  453. { extract WE handle }
  454.         err := AEGetParamPtr(ae, keyAETSMDocumentRefCon, typeLongInteger, returnedType, @hWE, SizeOf(hWE), actualSize);
  455.         if (err <> noErr) then
  456.             goto 1;
  457.  
  458. { lock the WE record }
  459.         saveWELock := _WESetHandleLock(hWE, true);
  460.         pWE := hWE^;
  461.  
  462. { if there's no active input area, return errOffsetInvalid }
  463.         if (pWE^.tsmAreaStart < 0) then
  464.             begin
  465.                 err := errOffsetInvalid;
  466.                 goto 1;
  467.             end;
  468.  
  469. { extract the offset parameter }
  470.         err := AEGetParamPtr(ae, keyAEOffset, typeLongInteger, returnedType, @offset, SizeOf(offset), actualSize);
  471.         if (err <> noErr) then
  472.             goto 1;
  473.  
  474. { offset is relative to the beginning of the active input area; we want an absolute offset }
  475.         offset := offset + pWE^.tsmAreaStart;
  476.  
  477. { make sure the offset is within the input area }
  478.         if (offset < pWE^.tsmAreaStart) or (offset >= pWE^.tsmAreaEnd) then
  479.             begin
  480.                 err := errOffsetInvalid;
  481.                 goto 1;
  482.             end;
  483.  
  484. { find the position corresponding to the given offset (in long coordinates) }
  485.         WEGetPoint(offset, thePoint, lineHeight, hWE);
  486.         thePoint.v := thePoint.v + lineHeight;
  487.  
  488. { make sure offset is within view rectangle }
  489.         if (not WELongPointInLongRect(thePoint, pWE^.viewRect)) then
  490.             begin
  491.                 err := errOffsetIsOutsideOfView;
  492.                 goto 1;
  493.             end;
  494.  
  495. { convert the point to short... }
  496.         WELongPointToPoint(thePoint, position);
  497.  
  498. { ...and global coordinates }
  499.         GetPort(savePort);
  500.         SetPort(pWE^.port);
  501.         LocalToGlobal(position);
  502.         SetPort(savePort);
  503.  
  504. { add keyAEPoint parameter to the reply Apple event }
  505.         err := AEPutParamPtr(reply, keyAEPoint, typeQDPoint, @position, SizeOf(position));
  506.         if (err <> noErr) then
  507.             goto 1;
  508.  
  509. { add keyAETSMTextFont parameter to the reply Apple event }
  510.         err := AEPutParamPtr(reply, keyAETSMTextFont, typeShortInteger, @pWE^.nullStyle.runStyle.tsFont, SizeOf(pWE^.nullStyle.runStyle.tsFont));
  511.         if (err <> noErr) then
  512.             goto 1;
  513.  
  514. { add keyAETSMTextPointSize parameter to the reply Apple event }
  515.         err := AEPutParamPtr(reply, keyAETSMTextPointSize, typeShortInteger, @pWE^.nullStyle.runStyle.tsSize, SizeOf(pWE^.nullStyle.runStyle.tsSize));
  516.         if (err <> noErr) then
  517.             goto 1;
  518.  
  519. { add keyAETextLineAscent parameter to the reply Apple event }
  520.         err := AEPutParamPtr(reply, keyAETextLineAscent, typeShortInteger, @pWE^.nullStyle.runAscent, SizeOf(pWE^.nullStyle.runAscent));
  521.         if (err <> noErr) then
  522.             goto 1;
  523.  
  524. { add keyAETextLineHeight parameter to the reply Apple event }
  525.         err := AEPutParamPtr(reply, keyAETextLineHeight, typeShortInteger, @pWE^.nullStyle.runHeight, SizeOf(pWE^.nullStyle.runHeight));
  526.         if (err <> noErr) then
  527.             goto 1;
  528.  
  529. { clear result code }
  530.         err := noErr;
  531.  
  532. 1:
  533. { unlock the WE record }
  534.         if (hWE <> nil) then
  535.             if (_WESetHandleLock(hWE, saveWELock)) then
  536.                 ;
  537.  
  538. { return result code }
  539.         _WEHandleOffsetToPosition := err;
  540.  
  541.     end;  { _WEHandleOffsetToPosition }
  542.  
  543. {$IFC WASTE_SEGMENT}
  544. {$S WASTE_INIT}
  545. {$ENDC}
  546.  
  547.     function WEInstallTSMHandlers: OSErr;
  548.         label
  549.             1;
  550.         var
  551.             err: OSErr;
  552.     begin
  553.  
  554. { the first time we're called, create routine descriptors for our Apple event handlers }
  555.         if (_weUpdateActiveInputAreaHandler = nil) then
  556.             begin
  557.                 _weUpdateActiveInputAreaHandler := NewAEEventHandlerProc(@_WEHandleUpdateActiveInputArea);
  558.                 _wePositionToOffsetHandler := NewAEEventHandlerProc(@_WEHandlePositionToOffset);
  559.                 _weOffsetToPositionHandler := NewAEEventHandlerProc(@_WEHandleOffsetToPosition);
  560.             end;
  561.  
  562. { install Apple Event handlers to be used by Text Service components }
  563.         err := AEInstallEventHandler(kTextServiceClass, kUpdateActiveInputArea, _weUpdateActiveInputAreaHandler, 0, false);
  564.         if (err <> noErr) then
  565.             goto 1;
  566.  
  567.         err := AEInstallEventHandler(kTextServiceClass, kPos2Offset, _wePositionToOffsetHandler, 0, false);
  568.         if (err <> noErr) then
  569.             goto 1;
  570.  
  571.         err := AEInstallEventHandler(kTextServiceClass, kOffset2Pos, _weOffsetToPositionHandler, 0, false);
  572.         if (err <> noErr) then
  573.             goto 1;
  574.  
  575. { clear result code }
  576.         err := noErr;
  577.  
  578. 1:
  579. { return result code }
  580.         WEInstallTSMHandlers := err;
  581.  
  582.     end;  { WEInstallTSMHandlers }
  583.  
  584.     function WERemoveTSMHandlers: OSErr;
  585.         label
  586.             1;
  587.         var
  588.             err: OSErr;
  589.     begin
  590.  
  591. { return an error code if WEInstallTSMHandlers has never been called }
  592.         err := errAEHandlerNotFound;
  593.         if (_weUpdateActiveInputAreaHandler = nil) then
  594.             goto 1;
  595.  
  596. { remove the handlers }
  597.         err := AERemoveEventHandler(kTextServiceClass, kUpdateActiveInputArea, _weUpdateActiveInputAreaHandler, false);
  598.         if (err <> noErr) then
  599.             goto 1;
  600.  
  601.         err := AERemoveEventHandler(kTextServiceClass, kPos2Offset, _wePositionToOffsetHandler, false);
  602.         if (err <> noErr) then
  603.             goto 1;
  604.  
  605.         err := AERemoveEventHandler(kTextServiceClass, kOffset2Pos, _weOffsetToPositionHandler, false);
  606.         if (err <> noErr) then
  607.             goto 1;
  608.  
  609. { clear result code }
  610.         err := noErr;
  611.  
  612. 1:
  613. { return result code }
  614.         WERemoveTSMHandlers := err;
  615.  
  616.     end;  { WERemoveTSMHandlers }
  617.  
  618. end.